home *** CD-ROM | disk | FTP | other *** search
/ 3D Games - Real-time Rend…ng & Software Technology / 3D Games - Real-time Rendering & Software Technology.iso / flysdk / plugin / bezobj / bezier_loft.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-03  |  5.3 KB  |  240 lines

  1. #include "..\..\lib\Fly3D.h"
  2. #include "bezobj.h"
  3.  
  4. void bezier_loft::init()
  5. {
  6.     patch.reset();
  7.     if (sfmesh) 
  8.         delete sfmesh;
  9.     sfmesh=0;
  10.     if (shape && path && source)
  11.     {
  12.         pos=path->pivot;
  13.         patch.build_loft(shape,path,texpic,lm,tileu,tilev);
  14.         build_stripfan();
  15.     }
  16. }
  17.  
  18. bsp_object *bezier_loft::clone()
  19. {
  20.     bezier_loft *tmp=new bezier_loft;
  21.     *tmp=*this;
  22.     tmp->source=this;
  23.     return tmp;
  24. }
  25.  
  26. int bezier_loft::get_custom_param_desc(int i,param_desc *pd)
  27. {
  28.     if (pd!=0)
  29.     switch(i)
  30.     {
  31.     case 0:
  32.         pd->type='z';
  33.         pd->data=&shape;
  34.         strcpy(pd->name,"shape");
  35.         break;
  36.     case 1:
  37.         pd->type='z';
  38.         pd->data=&path;
  39.         strcpy(pd->name,"path");
  40.         break;
  41.     case 2:
  42.         pd->type='p';
  43.         pd->data=&texpic;
  44.         strcpy(pd->name,"texpic");
  45.         break;
  46.     case 3:
  47.         pd->type='i';
  48.         pd->data=&lm;
  49.         strcpy(pd->name,"lm");
  50.         break;
  51.     case 4:
  52.         pd->type='f';
  53.         pd->data=&tileu;
  54.         strcpy(pd->name,"tileu");
  55.         break;
  56.     case 5:
  57.         pd->type='f';
  58.         pd->data=&tilev;
  59.         strcpy(pd->name,"tilev");
  60.         break;
  61.     }
  62.     return 6;
  63. }
  64.  
  65. void bezier_loft::draw()
  66. {
  67.     if (sfmesh)
  68.     {
  69.         glPushMatrix();
  70.         glTranslatef(pos.x,pos.y,pos.z);
  71.         glMultMatrixf((float *)&mat);
  72.  
  73.         glColor3ub(255,255,255);
  74.         sfmesh->draw(7);
  75.  
  76.         glPopMatrix();
  77.     }
  78. }
  79.  
  80. void bezier_loft::build_stripfan()
  81. {
  82.     // allocate new stripfan mesh
  83.     if (sfmesh) delete sfmesh;
  84.     sfmesh=new stripfan_mesh;
  85.  
  86.     int i,j,k,ns;
  87.     float u,v;
  88.     vector z[2];
  89.  
  90.     if (flyengine->appid==FLYAPPID_LIGHTBSP)
  91.     {
  92.         // create lightmap for patch
  93.         int lightmapsx=(int)(shape->length()/flyengine->lmpxsize);
  94.         int lightmapsy=(int)(path->length()/flyengine->lmpxsize);
  95.         if (lightmapsx>MAX_CURVE_LMPIXELS)
  96.             lightmapsx=MAX_CURVE_LMPIXELS;
  97.         if (lightmapsy>MAX_CURVE_LMPIXELS)
  98.             lightmapsy=MAX_CURVE_LMPIXELS;
  99.         ((bezier_loft *)source)->lm=lm=flyengine->add_lightmap(lightmapsx,lightmapsy);
  100.         memset(flyengine->lm[lm]->bmp,flyengine->amblight,flyengine->lm[lm]->bytesxy);
  101.     }
  102.  
  103.     // compute number of vertices in u and v base on curveerr
  104.     // to setup an LOD mesh where each point in the mesh lies in the patch surface
  105.     float *pointsu=new float[MAX_CURVE_VERTS];
  106.     int nvu=shape->adaptative_subdiv(flyengine->curveerr,pointsu,MAX_CURVE_VERTS);
  107.     float *pointsv=new float[MAX_CURVE_VERTS];
  108.     int nvv=path->adaptative_subdiv(flyengine->curveerr,pointsv,MAX_CURVE_VERTS);
  109.  
  110.     // compute number of strips
  111.     ns=nvu-1;
  112.  
  113.     // for each strip
  114.     k=0;
  115.     for( i=0;i<ns;i++ )
  116.     {
  117.         // create strip
  118.         sfmesh->add_stripfan(nvv*2,texpic,lm);
  119.  
  120.         // for each pair of vertices
  121.         for( j=0;j<nvv;j++ )
  122.         {
  123.             // evaluate vertex position, texture and lightmap coordinates
  124.  
  125.             u=pointsu[i+1];
  126.             v=pointsv[j];
  127.             patch.evaluate(PATCH_EVAL_POINT|PATCH_EVAL_TEXTCOORD,u,v,z);
  128.             sfmesh->vertdata[k].pos=z[0];
  129.             sfmesh->vertdata[k].u=z[1].x;
  130.             sfmesh->vertdata[k].v=z[1].y;
  131.             sfmesh->vertdata[k].ul=z[1].z;
  132.             sfmesh->vertdata[k].vl=z[1].w;
  133.             k++;
  134.  
  135.             u=pointsu[i];
  136.             patch.evaluate(PATCH_EVAL_POINT|PATCH_EVAL_TEXTCOORD,u,v,z);
  137.             sfmesh->vertdata[k].pos=z[0];
  138.             sfmesh->vertdata[k].u=z[1].x;
  139.             sfmesh->vertdata[k].v=z[1].y;
  140.             sfmesh->vertdata[k].ul=z[1].z;
  141.             sfmesh->vertdata[k].vl=z[1].w;
  142.             k++;
  143.         }
  144.     }
  145.  
  146.     delete pointsu;
  147.     delete pointsv;
  148.  
  149.     if (objmesh) delete objmesh;
  150.     objmesh=sfmesh->build_mesh();
  151.     objmesh->pivotpos=pos;
  152. }
  153.  
  154. void bezier_loft::illuminate_patch(vector& p,float rad,vector& color,int shadows)
  155. {
  156.     int i,j,k;
  157.     float dist,u,v;
  158.  
  159.     // get lightmap applied to patch
  160.     light_map *l=flyengine->lm[lm];
  161.     unsigned char *uc;
  162.     
  163.     // get light position in patch local coordinates
  164.     vector center=(p-pos)*mat_t,point,dir;
  165.     rad*=rad;
  166.  
  167.     // for each lightmap pixel in y
  168.     for( j=0;j<l->sizey;j++ )
  169.     {
  170.         uc=&l->bmp[j*l->bytesx];
  171.         v=(j+0.5f)/l->sizey;
  172.         // for each lightmap pixel in x
  173.         for( i=0;i<l->sizex;i++ )
  174.         {
  175.         u=(i+0.5f)/l->sizex;
  176.  
  177.         // get lightmap pixel position in the patch surface
  178.         patch.evaluate(PATCH_EVAL_POINT,u,v,&point);
  179.         
  180.         // check if point is inside light radius
  181.         dir=point-center;
  182.         dist=dir.x*dir.x+dir.y*dir.y+dir.z*dir.z;
  183.         if (dist>rad)
  184.             uc+=3;
  185.         else 
  186.             {
  187.             // compute lighting factor based on light radius and pixel distance
  188.             dist=(1.0f-dist/rad)*255.0f;
  189.  
  190.             // if shadows required, multiply dot product of patch normal and 
  191.             // light direction and check for collision
  192.             if (shadows==2)
  193.                 {
  194.                 vector normal;
  195.                 dir.normalize();
  196.                 patch.evaluate(PATCH_EVAL_NORMAL,u,v,&normal);
  197.                 float dot=-vec_dot(dir,normal);
  198.                 flyengine->excludecollision=this;
  199.                 if (dot<0.0f ||
  200.                     flyengine->collision_test(flyengine->bsp,center,point))
  201.                     {
  202.                     uc+=3;
  203.                     flyengine->excludecollision=0;
  204.                     continue;
  205.                     }
  206.                 flyengine->excludecollision=0;
  207.                 dist*=dot;
  208.                 }
  209.  
  210.             // apply colors to lightmap
  211.  
  212.             k=(int)(color.x*dist)+(int)(*uc);
  213.             *(uc++)=k>255?255:k;
  214.  
  215.             k=(int)(color.y*dist)+(int)(*uc);
  216.             *(uc++)=k>255?255:k;
  217.  
  218.             k=(int)(color.z*dist)+(int)(*uc);
  219.             *(uc++)=k>255?255:k;
  220.             }
  221.         }
  222.     }
  223.     
  224.     l->lastupdate=flyengine->cur_step;
  225. }
  226.  
  227. int bezier_loft::message(vector& p,float rad,int msg,int param,void *data)
  228. {
  229.     if (msg==FLYOBJM_ILLUM && (flyengine->mapmode&MAPPING_LIGHTMAP))
  230.     {
  231.         if (lm>=0 && lm<flyengine->nlm)
  232.             illuminate_patch(p,rad,*((vector *)data),param);
  233.     }
  234.     else if (msg==FLYOBJM_CHANGEPARAM)
  235.             if (param>=0 || 
  236.                 ((param_desc *)data)->data==&flyengine->curveerr)
  237.                 init();
  238.     return 0;
  239. }
  240.